﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using xKnight.Attacker.CSRF;
using xKnight.Data;
using xKnight.Models;
using xKnight.WebCrawling;
using xKnight.WebCrawling.Core;

namespace xKnight.Attacking.CSRF
{
    internal class CsrfAttackerAgent : AttackerAgent
    {

        #region Properties

        protected CsrfAttackingSharedResource SharedResource
        {
            get
            {
                return _attackingSharedResource as CsrfAttackingSharedResource;
            }
        }

        #endregion

        #region Constructors

        public CsrfAttackerAgent(AttackingSharedReource attackingSharedResource)
            :base(attackingSharedResource)
        {

        }

        #endregion
        internal override void Attack()
        {
            Webpage page = null;

            while ((page = GetNotVistedPage()) != null)
            {
                DoAttack(page);
            }
        }

        private void DoAttack(Webpage page)
        {
            CsrfAttack csrfAttack = new CsrfAttack();
            csrfAttack.AttackId = SharedResource.SharedAttack.Id;
            csrfAttack.StartTime = DateTime.Now;
            csrfAttack.WebpageId = page.Id;

            WebCrawlingStatus status =
                WebCrawler.DownloadPage(page.Url, DataLayer.GeHostCookies(page)).WebCrawlingStatus;

            csrfAttack.ResponsePage = page.Html;
            DataLayer.Save(csrfAttack);

            if (status == WebCrawlingStatus.DownloadingFinished)
            {
                Form[] newForms = WebCrawler.ExtractForms(page.Url, page.Html);

                for (int i = 0; i < newForms.Length; i++)
                {
                    newForms[i].WebpageId = page.Id;
                    DataLayer.Save(newForms[i]);

                    CsrfAttackForm csrfAttackForm = new CsrfAttackForm();
                    csrfAttackForm.CsrfAttackId = csrfAttack.Id;
                    csrfAttackForm.FormId = newForms[i].Id;

                    DataLayer.Save(csrfAttackForm);

                    var announceItem = new CsrfAttackAnnounceItem(newForms[i].Action,newForms[i].Method,
                        AttackStatus.AttackFinished, SharedResource, "", DateTime.Now, 0, "", page.Url);

                    OnAgentAttackAnnounced(announceItem);
                }
            }
           
            csrfAttack.FinishTime = DateTime.Now;
            DataLayer.Save(csrfAttack);
        }

        private Webpage GetNotVistedPage()
        {
            Webpage page= null;
            lock (SharedResource.SharedLock)
            {
                page = SharedResource.SharedQueue.Count != 0 ? SharedResource.SharedQueue.Dequeue() : null;
            }

            return page;
        }

    }
}
